package com.mysite.task.service;

import java.lang.reflect.Method;

import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.lite.api.JobScheduler;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.lite.internal.schedule.JobRegistry;
import com.dangdang.ddframe.job.lite.internal.schedule.JobScheduleController;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;

@Component
public class ElasticJobService implements ApplicationContextAware {

    @Autowired
    private ZookeeperRegistryCenter regCenter;

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 动态添加
     * 
     * @param jobClass
     * @param cron
     * @param shardingTotalCount
     * @param shardingItemParameters
     */
    public void addSimpleJobScheduler(final Class<? extends SimpleJob> jobClass, final String cron,
            final int shardingTotalCount, final String shardingItemParameters) {
        JobCoreConfiguration coreConfig = JobCoreConfiguration.newBuilder(jobClass.getSimpleName(), cron, shardingTotalCount)
                .shardingItemParameters(shardingItemParameters).build();
        SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(coreConfig, jobClass.getCanonicalName());

        LiteJobConfiguration liteJobConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).build();
        JobScheduler jobScheduler = new JobScheduler(regCenter, liteJobConfig);

        try {
            // 以下 为jobScheduler 初始化， 等同于调用 jobScheduler.init()
            LiteJobConfiguration liteJobConfigFromRegCenter = jobScheduler.getSchedulerFacade()
                    .updateJobConfiguration(liteJobConfig);
            JobRegistry.getInstance().setCurrentShardingTotalCount(liteJobConfigFromRegCenter.getJobName(),
                    liteJobConfigFromRegCenter.getTypeConfig().getCoreConfig().getShardingTotalCount());

            // 反射获取 Scheduler
            Method createSchedulerMethod = JobScheduler.class.getDeclaredMethod("createScheduler");
            if (!createSchedulerMethod.isAccessible()) {
                createSchedulerMethod.setAccessible(true);
            }
            Scheduler scheduler = (Scheduler) createSchedulerMethod.invoke(jobScheduler);
            // 反射获取 jobDetail
            Method createJobDetailMethod = JobScheduler.class.getDeclaredMethod("createJobDetail", String.class);
            if (!createJobDetailMethod.isAccessible()) {
                createJobDetailMethod.setAccessible(true);
            }
            JobDetail jobDetail = (JobDetail) createJobDetailMethod.invoke(jobScheduler,
                    liteJobConfigFromRegCenter.getTypeConfig().getJobClass());
            // 把spring bean 设置为job 执行时的对象
            SimpleJob simpleJob = applicationContext.getBean(jobClass);
            if (simpleJob != null) {
                jobDetail.getJobDataMap().put(JobScheduler.ELASTIC_JOB_DATA_MAP_KEY, simpleJob);
            }

            JobScheduleController jobScheduleController = new JobScheduleController(scheduler, jobDetail,
                    liteJobConfigFromRegCenter.getJobName());
            JobRegistry.getInstance().registerJob(liteJobConfigFromRegCenter.getJobName(), jobScheduleController,
                    regCenter);
            jobScheduler.getSchedulerFacade().registerStartUpInfo(!liteJobConfigFromRegCenter.isDisabled());
            jobScheduleController.scheduleJob(liteJobConfigFromRegCenter.getTypeConfig().getCoreConfig().getCron());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}